// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CloudQueueExtensionsXml.cs" company="AzureContrib (Open source library http://azurecontrib.codeplex.com)">
//   Microsoft Public License (Ms-PL)
// </copyright>
// <summary>
//   Exception for errors when handling Windows Azure Cloud Drives.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Xml.Serialization;

using Microsoft.WindowsAzure.StorageClient;

namespace AzureContrib.WindowsAzure.StorageClient
{
	/// <summary>
	/// Extensions on <see cref="Microsoft.WindowsAzure.StorageClient.CloudQueueMessage"/> using xml
	/// </summary>
	public static class CloudQueueExtensionsXml
	{
		/// <summary>
		/// Deserialize a <see cref="Microsoft.WindowsAzure.StorageClient.CloudQueueMessage"/> to an instance of the given type <typeparamref name="T"/>.
		/// </summary>
		/// <typeparam name="T">The type of oject the message is serialized from.</typeparam>
		/// <param name="cloudQueueMessage">The actual message on the queue.</param>
		/// <returns>An instance of type <typeparamref name="T"/></returns>
		[SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", Justification = "Assumes.NotNull handles null checking.", Scope = "method")]
		public static T PayloadXml<T>(this CloudQueueMessage cloudQueueMessage)
		{
			Assumes.NotNull(cloudQueueMessage, "cloudQueueMessage");
			var serializer = new XmlSerializer(typeof(T));
			T t;
			using (var stream = new MemoryStream(cloudQueueMessage.AsBytes))
			{
				t = (T)serializer.Deserialize(stream);
			}

			return t;
		}

		/// <summary>
		/// Serialize a <see cref="Microsoft.WindowsAzure.StorageClient.CloudQueueMessage"/> form an instance.
		/// </summary>
		/// <typeparam name="T">The type of instance to create a message <see cref="Microsoft.WindowsAzure.StorageClient.CloudQueueMessage"/> from.</typeparam>
		/// <param name="instance">
		/// The actual message on the queue.
		/// </param>
		/// <returns>
		/// A <see cref="Microsoft.WindowsAzure.StorageClient.CloudQueueMessage"/> serialized from the data in the <paramref name="instance"/>
		/// </returns>
		[SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", Justification = "Assumes.NotNull handles null checking.", Scope = "method")]
		public static CloudQueueMessage ToCloudQueueMessageXml<T>(this T instance) where T : class
		{
			Assumes.NotNull(instance, "instance");
			var serializer = new XmlSerializer(instance.GetType());
			byte[] byteArray;

			using (var memoryStream = new MemoryStream())
			{
				serializer.Serialize(memoryStream, instance);

				if (memoryStream.Length > CloudQueueMessageExtensions.MaxMessageBuffer)
				{
					throw new ArgumentException("The message to serialize is greater than 8Kb. Type: {0}, .ToString(): {1}".F(instance.GetType().FullName, instance));
				}

				byteArray = new byte[memoryStream.Length];
				memoryStream.Position = 0;
				memoryStream.Read(byteArray, 0, (int)memoryStream.Length);
			}

			return new CloudQueueMessage(byteArray);
		}
	}
}